package ru.spbau.bytecode.gui;

import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import ru.spbau.bytecode.graph.CompositeVertex;
import ru.spbau.bytecode.graph.Graph;
import ru.spbau.bytecode.graph.Vertex;

public class CheckBoxTree extends JTree {
	
	private final List<ListUpdateListener> listeners =
		new LinkedList<ListUpdateListener>();

	public CheckBoxTree() {
		setModel(new DefaultTreeModel(null));
		setCellRenderer(new CheckBoxTreeNodeRenderer());
		addMouseListener(new MouseListener());
	}
	
	public void addListUpdateListener(ListUpdateListener listener) {
		listeners.add(listener);
	}
	
	public void removeListUpdateListener(ListUpdateListener listener) {
		listeners.remove(listener);
	}

	public void setGraph(Graph graph) {
		DefaultMutableTreeNode root = new DefaultMutableTreeNode("Project");
		for (CompositeVertex compositeVertex : graph.getVertices()) {
			DefaultMutableTreeNode compositeVertexNode = new DefaultMutableTreeNode(
					compositeVertex);
			root.add(compositeVertexNode);

			for (Vertex innerVertex : compositeVertex.getInnerVertices()) {
				DefaultMutableTreeNode innerVertexNode = new DefaultMutableTreeNode(
						innerVertex);
				compositeVertexNode.add(innerVertexNode);
			}
		}

		setModel(new DefaultTreeModel(root));
	}

	private class MouseListener extends MouseAdapter {

		@Override
		public void mousePressed(MouseEvent e) {
			TreePath path = getClosestPathForLocation(e.getX(), e.getY());
			if (path == null) {
				return;
			}
			
			int row = getRowForPath(path);
			Rectangle bounds = getRowBounds(row);
			if (!(bounds.contains(e.getPoint()))) {
				return;
			}
			
			DefaultMutableTreeNode node =
				(DefaultMutableTreeNode)path.getLastPathComponent();

			if (node.isLeaf()) {
				DefaultMutableTreeNode parent = (DefaultMutableTreeNode)node.getParent();
				Object parentObject = parent.getUserObject();
				if (parentObject instanceof Vertex) {
					Vertex compositeVertex = (CompositeVertex)parentObject;
					if (!compositeVertex.isVisible()) {
						return;
					}
				}
			}
			
			
			Object data = node.getUserObject();

			if (data instanceof Vertex) {
				Vertex v = (Vertex) (data);
				v.invert();
				repaint();
				
				for (ListUpdateListener listener: listeners) {
					listener.listUpdated(new ListUpdateEvent(this));
				}
//				fireValueChanged(new TreeSelectionEvent(
//						CheckBoxTree.this, null, false, null, null));
			}
		}
	}
}
